<?php

namespace App\Http\Controllers;

use App\Http\Resources\Order as OrderResource;
use App\Models\Address;
use App\Models\GameRecord;
use App\Models\Order;
use App\Models\OrderExtension;
use App\Models\OrderWare;
use App\Services\Doll;
use App\Services\Kuaidi100;
use App\Support\ResourceCollection;
use App\Support\Time;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class OrdersController extends Controller
{
    /**
     * 订单列表
     *
     * @param Request $request
     * @return ResourceCollection
     */
    public function index(Request $request)
    {
        $filter = [];

        if ($request->filled('status')) {
            $filter['status'] = $request->get('status');
        }

        $orders = $request->user()->orders()->where($filter)->orderByDesc('id')
            ->with('wares')->simplePaginate(per_page());
        return new ResourceCollection($orders);
    }

    /**
     * 订单详情
     *
     * @param Order $order
     * @return \Illuminate\Http\JsonResponse|Resource
     */
    public function show(Order $order)
    {
        if (Auth::id() != $order->user_id) {
            return access_denied();
        }

        return new OrderResource($order);
    }

    /**
     * 领取奖品
     *
     * 按照发货方式创建订单，先在本系统中完成领取，再向“硬件系统”发起下单请求
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Services\Doll $doll
     * @return OrderResource|\Illuminate\Http\JsonResponse
     *
     * @throws \Exception
     */
    public function store(Request $request, Doll $doll)
    {
        /** @var \App\Models\User $user */
        $user = $request->user();

        // 验证地址
        /** @var \App\Models\Address $address */
        $address = Address::findOrFail($request->post('address_id'));
        if ($address->user_id != $user->id) {
            return access_denied();
        }

        // 最多领取 50 个
        $ids = array_slice($request->post('doll_record_ids'), 0, 50);
        
        $wareIds = GameRecord::whereIn('id', $ids)->pluck('ware_id')->all();
        $goods = $doll->getGoodsInfos($wareIds);
        
        $orders = [];

        DB::beginTransaction();

        // 按照发货方式创建订单，完成领取
        try {
            // 验证中奖记录
            // 加锁：select for update
            $records = GameRecord::where([
                'user_id' => $user->id,
                'operate_result' => GameRecord::OPERATE_SUCCESS,
                'ware_status' => GameRecord::WARE_STATUS_RECEIVABLE,
            ])->where('ware_id', '!=', 0)->whereIn('id', $ids)->lockForUpdate()->get();

            if ($records->isEmpty()) {
                throw ValidationException::withMessages(['无中奖记录']);
            }
            
            // 根据发货方式进行分组
            $groups = $records->groupBy(function ($record) use ($goods) {
                return $goods[$record->ware_id]['send_type'];
            });
            
            foreach ($groups as $sendType => $groupRecords) {
                $wares = game_records_to_wares($groupRecords);
                
                // 生成订单
                $order = Order::create([
                    'user_id' => $user->id,
                    'status' => Order::STATUS_WAIT,
                    'order_sn' => $user->randomTradeNo(),
                    'send_type' => $sendType,
                ]);

                // 订单扩展记录
                OrderExtension::create(object_only($address, [
                    'province_id', 'city_id', 'district_id', 'address', 'consignee', 'phone',
                ]) + ['order_id' => $order->id]);

                // 订单商品记录
                $array = [];
                foreach ($wares as $ware) {
                    $array[] = [
                        'order_id' => $order->id,
                        'ware_id' => $ware['ware_id'],
                        'name' => $ware['ware_name'],
                        'image' => $ware['ware_image'],
                        'num' => $ware['num'],
                    ];
                }
                OrderWare::insert($array);

                // 更新记录状态为已领取
                GameRecord::whereIn('id', $groupRecords->pluck('id'))->update([
                    'ware_status' => GameRecord::WARE_STATUS_RECEIVED,
                    'order_id' => $order->id,
                ]);

                $orders[] = ['order' => $order, 'wares' => $wares];
            }

            DB::commit();
        } catch (Exception $e) {
            DB::rollBack();
            
            throw $e;
        }
        
        // 逐个向“硬件系统”进行下单
        foreach ($orders as $item) {
            $result = doll_send_order($user, $address, $item['wares']);
            
            $item['order']->update(['out_order_id' => $result['order_id']]);
        }
        
        return $this->wrapData();
    }
    
    /**
     * 游戏机硬件系统订单回调
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Services\Doll $doll
     * @return \Illuminate\Http\JsonResponse
     */
    public function update(Request $request, Doll $doll)
    {
        $inputs = $request->all();
        if (! $doll->checkSign($inputs['sign'] ?? '', $inputs)) {
            return invalidation('验证失败');
        }
        
        DB::transaction(function () use ($inputs) {
            $outOrderId = $inputs['order_id'];
            /** @var \App\Models\Order $order */
            $order = Order::where('out_order_id', $outOrderId)->first();
            $order->update(['status' => Order::STATUS_SHIPPED]);
            
            $shipping = array_filter(array_only($inputs, ['shipping_no', 'shipping_name', 'shipping_com']));
            $shipping['shipped_at'] = Time::now();
            
            $order->extension->update($shipping);
        });
    }

    /**
     * 确认收货
     *
     * @param \App\Models\Order $order
     * @return array|\Illuminate\Http\JsonResponse
     */
    public function confirm(Order $order)
    {
        if ($order->user_id != Auth::id()) {
            return access_denied();
        }

        if ($order->status != Order::STATUS_SHIPPED) {
            return invalidation('订单不是发货状态');
        }

        $order->status = Order::STATUS_DONE;
        $order->save();

        return $this->wrapData();
    }

    /**
     * 删除订单
     *
     * @param Order $order
     * @return array|\Illuminate\Http\JsonResponse
     *
     * @throws \Exception
     */
    public function destroy(Order $order)
    {
        if ($order->user_id != Auth::id()) {
            return access_denied();
        }
        if ($order->status != Order::STATUS_DONE) {
            return invalidation('订单未完成');
        }
        $order->delete();
        
        return $this->wrapData();
    }

    /**
     * 物流查询
     *
     * @param Order $order
     * @param Kuaidi100 $kuaidi100
     * @return \Illuminate\Http\JsonResponse|Resource
     */
    public function logistics(Order $order, Kuaidi100 $kuaidi100)
    {
        $extension = $order->extension;

        if (!$extension) {
            return invalidation('订单物流信息不存在');
        }
        if ($order->user_id != Auth::id()) {
            return access_denied();
        }

        // 快递100运单查询
        $extension->logistics = $kuaidi100->traceInfo($extension->shipping_com, $extension->shipping_no);

        return new Resource($extension);
    }
}
